﻿using System;
using System.Linq;
using FlatRedBall;
using FlatRedBall.Graphics;
using FlatRedBall.Graphics.Particle;
using Microsoft.Xna.Framework;
using Rvz.Game.Main.Common;
using Rvz.Game.Main.Entities.Robots.States;
using Rvz.Game.Main.Inputs;
using Rvz.Game.Main.Rules;
using Rvz.Game.Main.State;

namespace Rvz.Game.Main.Entities.Robots
{
    public class Robot : EntityBase<Robot, RobotStateBase>
    {
        private double _timeSinceLastFiredProjectile;
        private readonly Text _healthDisplay;
        private readonly EmitterList _emitterList;
        private readonly Emitter _smokeEmission;
        private readonly Random _random = new Random();

        public Robot(string contentManagerName)
            : base(contentManagerName)
        {
            RobotAttributes = new RobotAttributes();
            _emitterList = FlatRedBallServices.Load<EmitterList>("Content\\Effects\\StackSmoke\\StackSmoke_SmallScale.emix", contentManagerName);
            _smokeEmission = _emitterList.First();
            _emitterList.AttachTo(this, true);

            //TODO: Add to UI Overlay/HUD
            _healthDisplay = TextManager.AddText(string.Empty);
            _healthDisplay.RelativeZVelocity = 0;
            _healthDisplay.AttachTo(this, false);
            _healthDisplay.SetColor(1, 0, 0);
        }

        public void HandleUpdateInput(GameState gameState, IRationalizedInputDevice inputDevice, GameTime gameTime)
        {
            HandleRobotMove(inputDevice);
            HandleRobotTurn(inputDevice);
            HandleFiringProjectiles(inputDevice, gameTime, gameState);
        }

        private void HandleRobotMove(IRationalizedInputDevice inputDevice)
        {
            var desiredXAddition = RobotAttributes.MoveSpeed * inputDevice.MoveX;
            var desiredYAddition = RobotAttributes.MoveSpeed * inputDevice.MoveY;

            var xAddition = (desiredXAddition - XVelocity);
            var yAddition = (desiredYAddition - YVelocity);

            XVelocity += xAddition;
            YVelocity += yAddition;
            CollisionShape.CollideAgainstMove(Helper.CameraCollision, 0, 1);
        }

        private void HandleRobotTurn(IRationalizedInputDevice inputDevice)
        {
            var rightStickMoveX = (RobotAttributes.MoveSpeed / 2) * (-inputDevice.TurnX / inputDevice.TurnSensitivity);
            RotationZVelocity += (rightStickMoveX - RotationZVelocity);
        }

        private void HandleFiringProjectiles(IRationalizedInputDevice gamePad, GameTime gameTime, GameState gameState)
        {
            if (gamePad.FireTrigger == 0)
            { return; }

            if (_timeSinceLastFiredProjectile >= 0 && _timeSinceLastFiredProjectile < RobotAttributes.CurrentWeapon.RateOfFire)
            { return; }

            ProjectileEngine.Fire(this, gameState);
            _timeSinceLastFiredProjectile = 0;
        }

        public override void HandleUpdate(GameState gameState, GameTime gameTime)
        {
            _timeSinceLastFiredProjectile += gameTime.ElapsedGameTime.TotalSeconds;
            ProjectileEngine.ProcessRules(gameState);
            _healthDisplay.DisplayText = RobotAttributes.Health.ToString();

            if (RobotAttributes.Health < 90)
            { _emitterList.TimedEmit(); }
        }

        public RobotAttributes RobotAttributes { get; set; }

        public bool IsDead()
        {
            return RobotAttributes.Health <= 0;
        }

        public void TakeDamage(int damage)
        {
            var damageAfterReductions = damage;
            if (RobotAttributes.Armor > 0)
            { damageAfterReductions -= RobotAttributes.ArmorDamageReduction; }
            if (damageAfterReductions <= 0)
            { return; }

            RobotAttributes.Health -= Math.Min(damageAfterReductions, RobotAttributes.Health);

            var frequency = Math.Round(RobotAttributes.Health * .01, 2);
            _smokeEmission.SecondFrequency = (float)frequency;
        }

        protected override float Scale { get { return 2f; } }
        protected override string SpriteFileLocation
        {
            get { return "Content\\Entities\\Robot\\robot_small.png"; }
        }

        public override void Destroy()
        {
            base.Destroy();
            TextManager.RemoveText(_healthDisplay);
        }
    }
}
